﻿// -----------------------------------------------------------------------
// <copyright file="BattleField.cs" company="Microsoft">
// TODO: Update copyright text.
// </copyright>
// -----------------------------------------------------------------------

namespace Cspl.AnimalFight.Lib
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Cspl.AnimalFight.Lib.Data;
    using Cspl.AnimalFight.Lib.EventHandlers;
    using Cspl.AnimalFight.Lib.Interfaces;

    /// <summary>
    /// TODO: Update summary.
    /// </summary>
    public class BattleField
    {
        #region Field
        private IList<AnimalBase> _animals;
        #endregion

        #region Constructor
        public BattleField()
        {
            this._animals = new List<AnimalBase>();
        }
        #endregion

        #region Property
        public IList<AnimalBase> Animals
        {
            get { return _animals; }
            private set { _animals = value; }
        }
        #endregion

        #region Method
        public AnimalBase this[string name]
        {
            get { return this._animals.FirstOrDefault(a => a.Name == name); }
            set
            {
                if (value != null)
                {
                    if (this._animals.FirstOrDefault(a => a.Name == name) == null)
                    {
                        IAttack attackingAnimal = value as IAttack;
                        if (attackingAnimal != null)
                        {
                            attackingAnimal.AttackEvent += new AttackDelegate(attackingAnimal_AttackEvent);
                        }

                        IDefend defendingAnimal = value as IDefend;
                        if (defendingAnimal != null)
                        {
                            defendingAnimal.DefendEvent += new DefendDelegate(defendingAnimal_DefendEvent);
                        }

                        this._animals.Add(value);
                    }
                    else
                    {
                        Console.WriteLine("{0} is already in BattleField.", value.Name);
                    }
                    
                }
            }
        }

        private void defendingAnimal_DefendEvent(object sender, DefendEventHandler e)
        {
            var defendingAnimal = this[e.AnimalName];

            if (defendingAnimal != null)
            {
                IDefend theAnimal = defendingAnimal as IDefend;
                if (theAnimal != null)
                {
                    theAnimal.IsDefending = true;
                }

                else
                {
                    Console.WriteLine("The animal {0} cannot defend itself.", e.AnimalName);
                }
            }
        }

        private void attackingAnimal_AttackEvent(object sender, AttackEventHandler e)
        {
            var animalTarget = this[e.AnimalTargetName];

            if (animalTarget != null)
            {
                if (animalTarget.HP > 0)
                {
                    IAttackable attackedAnimal = animalTarget as IAttackable;
                    if (attackedAnimal != null)
                    {
                        if (animalTarget.IsExistOnBattleField("attack"))
                        {
                            int left = Console.CursorLeft;
                            int top = Console.CursorTop;

                            Console.SetCursorPosition(30, top);
                            Console.ForegroundColor = ConsoleColor.Blue;
                            Console.WriteLine("{0}", animalTarget.Name);
                            Console.ResetColor();
                            Console.SetCursorPosition(30, top + 1);
                            Console.WriteLine("HP = {0}", animalTarget.HP);
                            Console.SetCursorPosition(30, top + 2);
                            Console.WriteLine("AP = {0}", animalTarget.AP);
                            Console.SetCursorPosition(30, top + 3);
                            Console.WriteLine("DP = {0}", animalTarget.DP);


                            Console.SetCursorPosition(left, top);
                            Console.ForegroundColor = ConsoleColor.Green;
                            Console.WriteLine("{0}", (sender as AnimalBase).Name);
                            Console.ResetColor();
                            Console.WriteLine("HP = {0}", (sender as AnimalBase).HP);
                            Console.WriteLine("AP = {0}", (sender as AnimalBase).AP);
                            Console.WriteLine("DP = {0}", (sender as AnimalBase).DP);


                            Console.WriteLine("{0} is attacked with AP={1}.", e.AnimalTargetName, e.AP);
                            attackedAnimal.Attacked(e.AP);
                        }
                    }
                }
                else
                {
                    Console.WriteLine("Object can't be attacked because it has minus HP");
                }
            }
        }

        public bool Command(string animalName, Commands command, string targetName)
        {
            var animal = this[animalName];
            var target = this[targetName];
            bool result = true;
            
            if (animal != null)
            {
                switch (command)
                {
                    case Commands.Attack:
                        if (animal is IAttack)
                        {
                            //add target checking if it is not null
                            if (target != null) 
                            {
                                if (target.IsExistOnBattleField("attack"))
                                {
                                    (animal as IAttack).Attack(targetName);
                                    int left = Console.CursorLeft;
                                    int top = Console.CursorTop;

                                    Console.SetCursorPosition(30, top);
                                    Console.ForegroundColor = ConsoleColor.Blue;
                                    Console.WriteLine("{0}", target.Name);
                                    Console.ResetColor();
                                    Console.SetCursorPosition(30, top + 1);
                                    Console.WriteLine("HP = {0}", target.HP);
                                    Console.SetCursorPosition(30, top + 2);
                                    Console.WriteLine("AP = {0}", target.AP);
                                    Console.SetCursorPosition(30, top + 3);
                                    Console.WriteLine("DP = {0}", target.DP);


                                    Console.SetCursorPosition(left, top);
                                    Console.ForegroundColor = ConsoleColor.Green;
                                    Console.WriteLine("{0}", animal.Name);
                                    Console.ResetColor();
                                    Console.WriteLine("HP = {0}", animal.HP);
                                    Console.WriteLine("AP = {0}", animal.AP);
                                    Console.WriteLine("DP = {0}", animal.DP);

                                    Console.WriteLine();
                                }
                            }
                            //print message if target is null
                            else
                            {
                                Console.WriteLine("Animal {0} is not exists.", targetName);
                            }
                        }

                        else
                        {
                            Console.WriteLine("Animal {0} cannot attack.", animalName);
                            result = false;
                        }
                        break;
                    case Commands.Defend:
                        if (animal is IDefend)
                        {
                            (animal as IDefend).Defend();
                        }

                        else
                        {
                            Console.WriteLine("Animal {0} cannot defend.", animalName);
                            result = false;
                        }
                        break;
                    case Commands.Escape:
                        animal.Escape();
                        break;
                }
            }
            else
            {
                Console.WriteLine("Animal {0} is not exists.", animalName);

                //print message if target is null when attack command
                if (command == Commands.Attack && target == null) 
                {
                    Console.WriteLine("Animal {0} is not exists.", targetName);
                }

            }
            return result;
        }
        #endregion
    }

    public enum Commands { Attack, Defend, Escape }
}
